/**

This file is part of MaCI/GIMnet.

MaCI/GIMnet is free software: you can redistribute it and/or modify it 
under the terms of the GNU Lesser General Public License as published 
by the Free Software Foundation, either version 3 of the License, or 
(at your option) any later version.

MaCI/GIMnet is distributed in the hope that it will be useful, but WITHOUT 
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public 
License for more details.

You should have received a copy of the GNU Lesser General Public 
License along with GIMnet. (See COPYING.LESSER) If not, see 
<http://www.gnu.org/licenses/>.

**/
/**
 *
 * $Id: AudioContainer.cpp,v 1.3 2009-12-08 10:48:27 morsko Exp $
 *
 * \file
 * \brief AudioContainer class handling type conversions and stuff - Implementation.
 * \author Matthieu Myrsky <matthieu.myrsky@tkk.fi>
 *
 * \NOTE: Not ready yet!
 */

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "AudioContainer.hpp"
#include "AudioTypes.hpp"
#include "owndebug.h"

//*****************************************************************************
//*****************************************************************************
using namespace MaCI::Audio;
//*****************************************************************************
//*****************************************************************************
//*****************************************************************************
/** CAudioContainer default constructor.
 *
 */
CAudioContainer::CAudioContainer()
  :
  iAudioInfo(),
  iAudioDataPtr(NULL),
  iSize(0),      
  iIsOwnedBuffer(false)
{

}

//*****************************************************************************

/** Copy constructor.
 *
 */
CAudioContainer::CAudioContainer(const CAudioContainer &aAudioData)
  : iAudioInfo(),
    iAudioDataPtr(NULL),
    iSize(0),      
    iIsOwnedBuffer(false)
{
  this->Copy(aAudioData);
}
//*****************************************************************************

/**
 * Operator '=' working on non-const object -> Assign.
 */
CAudioContainer &CAudioContainer::operator=(CAudioContainer &aAudioData)
{
  this->Assign(aAudioData);
  return *this;
}
//*****************************************************************************

/**
 * Operator '=' working on const object -> Copy.
 */
CAudioContainer &CAudioContainer::operator=(const CAudioContainer &aAudioData)
{
  this->Copy(aAudioData);
  return *this;
}
//*****************************************************************************

/** Destructor.
 */
CAudioContainer::~CAudioContainer()
{
  Reset();
}
//*****************************************************************************

void CAudioContainer::Reset(void)
{
    dPrint(1,"Reseting");
  if (iIsOwnedBuffer && iAudioDataPtr != NULL) {
    dPrint(1,"Deleting iAudioDataPtr");
    delete[] iAudioDataPtr;
  }
  iAudioDataPtr = NULL;
  iSize = 0;
  iIsOwnedBuffer = false;
}
//*****************************************************************************

void CAudioContainer::Assign(CAudioContainer &aAudioData)
{
  // Take
  iAudioInfo = aAudioData.iAudioInfo;
  iAudioDataPtr = aAudioData.iAudioDataPtr;
  iSize = aAudioData.iSize;
  iIsOwnedBuffer = aAudioData.iIsOwnedBuffer;
  
  // Invalidate
  aAudioData.iAudioDataPtr = NULL;
  aAudioData.iSize = 0;
  aAudioData.iIsOwnedBuffer = false;
}
//*****************************************************************************

void CAudioContainer::Copy(const CAudioContainer &aAudioData)
{
  // Cleanup if buffer exists.
  if (this->iIsOwnedBuffer && this->iAudioDataPtr != NULL) 
    delete[] this->iAudioDataPtr;
  
  this->iAudioInfo = aAudioData.iAudioInfo;
  this->iAudioDataPtr = new unsigned char [this->iSize];
  memcpy(this->iAudioDataPtr,aAudioData.iAudioDataPtr,this->iSize);
  this->iSize = aAudioData.iSize;
  this->iIsOwnedBuffer = true;

}
//*****************************************************************************


bool CAudioContainer::SetAudioData(const unsigned char *aData, 
                                   const unsigned int aSize,
                                   const TAudioInfo aAudioInfo,
                                   const EAudioDataType aSrcType,
                                   const EAudioDataType aDestType)
{
  iAudioInfo = aAudioInfo;
  iSize = aSize;
  //Copy data
  this->iAudioDataPtr = new unsigned char [ this->iSize ];
  memcpy(this->iAudioDataPtr,aData,aSize);
  iIsOwnedBuffer =true;
  return false;
}
//*****************************************************************************

bool CAudioContainer::ConvertTo(const EAudioDataType aDestType)
{
  dPrint(1,"Conversions not implemented yet..");
  return false;
  
}
//*****************************************************************************

void CAudioContainer::GetAudioData(unsigned char **aData, unsigned int *aSize) {
  dPrint(10,"aData %u iAudioDataPtr %u",*aData,iAudioDataPtr);
 
  *aData = iAudioDataPtr;
  dPrint(10,"aData %u iAudioDataPtr %u",*aData,iAudioDataPtr);
  *aSize = iSize;
}
//*****************************************************************************
//*****************************************************************************
//*****************************************************************************
//*****************************************************************************
//*****************************************************************************
//*****************************************************************************
#ifdef COMPILE_AUDIOCONTAINER_STANDALONE_MAIN

#include "../../drivers/Audio/ALSA/ALSA.hpp"
int main(void){
  unsigned int frames =32;
  unsigned int sampleRate = 44100;
  debugInit();
  debugSetGlobalDebugLvl(1);


  CAlsa alsa;
  alsa.SetParameters(sampleRate,
                     (unsigned int)2,
                     EAudioFormatPCM16Bit,
                     EDataAccessRWInterleaved,
                     EDirectionCapture,
                     frames);

  //Open alsa driver
  if(alsa.Open()){
    dPrint(1,"Succesfully opened Alsa Driver.");
  }else{
    dPrint(1,"Failed to open Alsa driver.");
  }

  unsigned int numberOfFrames = 0;
  alsa.GetPeriodSize(numberOfFrames);
  dPrint(1,"numberOfFrames %d",numberOfFrames);
  unsigned int size = numberOfFrames * 4*100; /* 2 bytes/sample, 2 channels */
  char *buffer = (char *) malloc(size);
  dPrint(1,"recording...");
  alsa.GetAudio(buffer, numberOfFrames*100);
  dPrint(1,"recording ended");
  
  dPrint(1,"adding to container");
  CAudioContainer container;
  container.SetAudioData((unsigned char *)buffer,
                         size,
                         TAudioInfo(KAudioDataRaw,
                                    sampleRate,
                                    2,
                                    numberOfFrames),
                         KAudioDataRaw,
                         KAudioDataRaw);

  dPrint(1,"Getting from container");
  const unsigned char *buffer2;
  
  buffer2 = container.GetAudioDataPtr();


  CAlsa alsa2;
  alsa2.SetParameters(sampleRate,
                     2,
                     EAudioFormatPCM16Bit,
                     EDataAccessRWInterleaved,
                     EDirectionPlayback,
                     frames);

  //Open alsa driver
  if(alsa2.Open()){
    dPrint(1,"Succesfully opened Alsa 2Driver.");
  }else{
    dPrint(1,"Failed to open Alsa2 driver.");
  }
  dPrint(1,"Playing...");
  alsa2.PlayAudio((char *)buffer, numberOfFrames*100);
  dPrint(1,"Playing ended...");


  return 0;

}



#endif
